﻿using System;
using System.Collections.Generic;
using System.Drawing;
using GeometryCSharp;
using FIRADriverLibrary;
using AGHFiraPlayer.Drivers;

namespace AGHFiraPlayer
{
    public class AGHDriver 
    {
        public const int APPLICABILITY_MAX = 10000;
        public const int APPLICABILITY_MIN = 0;
        public const double ROBOT_DIAMETER = 0.1;

        public static RectangleF pitchArea;
        public double goalWidth;

        public static double goalStartY, goalEndY;
        public static Point2D target, home;

        public FIRADriver firaDriver;
        private RobotController goalkeeper;
        public RobotController GoalKeeper {
            get { return goalkeeper; }
        }

        private List<RobotController> robots = new List<RobotController>();
        public List<RobotController> Robots
        {
            get { return robots; }
        }

        private List<RobotController> oponents = new List<RobotController>();
        public List<RobotController> Oponents
        {
            get { return oponents; }
        }
        private Point2D LA, LD, GK, RD, RA;

        public AGHDriver(ref FIRADriver firaDriver, RectangleF pitchArea, float goalWidth)
        {
            this.firaDriver = firaDriver;
            AGHDriver.pitchArea = pitchArea;
            this.goalWidth = goalWidth;

            goalStartY = pitchArea.Top + pitchArea.Height / 2 - goalWidth / 2;
            goalEndY = goalStartY + goalWidth;

            home = new Point2D(pitchArea.Left, pitchArea.Top + pitchArea.Height / 2);
            target = new Point2D(pitchArea.Right, pitchArea.Top + pitchArea.Height / 2);
        }

        public void setStartPointsAndChooseGoalKeeper()
        {
            foreach (FIRARobotState robot in firaDriver.firaRobots)
            {
                if (robot.owned)
                    robots.Add(new RobotController(robot));
                else
                    oponents.Add(new RobotController(robot));
            }

            LA = new Point2D(home.x + pitchArea.Width / 2 - ROBOT_DIAMETER * 2, pitchArea.Top + pitchArea.Height / 2 - 6 * ROBOT_DIAMETER);
            LD = new Point2D(home.x + pitchArea.Width / 4 + ROBOT_DIAMETER, pitchArea.Top + pitchArea.Height / 2 - 3 * ROBOT_DIAMETER);
            GK = new Point2D(home.x + ROBOT_DIAMETER, pitchArea.Top + pitchArea.Height / 2);
            RD = new Point2D(home.x + pitchArea.Width / 4 + ROBOT_DIAMETER, pitchArea.Top + pitchArea.Height / 2 + 3 * ROBOT_DIAMETER);
            RA = new Point2D(home.x + pitchArea.Width / 2 - ROBOT_DIAMETER * 2, pitchArea.Top + pitchArea.Height / 2 + 6 * ROBOT_DIAMETER);

            assignRobotToStartPoint(GK);
            assignRobotToStartPoint(LA);
            assignRobotToStartPoint(LD);
            assignRobotToStartPoint(RD);
            assignRobotToStartPoint(RA);
        }

        private void assignRobotToStartPoint(Point2D choosenPoint)
        {
            RobotController choosenRobot = null;
            for (int i = 0; i < robots.Count; i++)
            {
                if (robots[i].startupPosition == null)
                {
                    choosenRobot = robots[i];
                    break;
                }
            }
            if (choosenRobot == null)
                return;
            Point2D currentPoint = new Point2D(choosenRobot.robotState.x, choosenRobot.robotState.y);
            double distance = currentPoint.GetDistance(choosenPoint);
            for (int i = 0; i < robots.Count; i++)
            {
                if (robots[i].startupPosition != null)
                    continue;
                double newDistance = new Point2D(robots[i].robotState.x, robots[i].robotState.y).GetDistance(GK);
                if (newDistance < distance)
                {
                    distance = newDistance;
                    choosenRobot = robots[i];
                }
            }
            choosenRobot.startupPosition = choosenPoint;
            if (choosenPoint == GK)
            {
                robots.Remove(choosenRobot);
                goalkeeper = choosenRobot;
            }
        }

        public void gameStateOff()
        {
            if (goalkeeper != null)
                goalkeeper.Stop();
            for (int i = 0; i < robots.Count; i++)
                robots[i].Stop();
        }

        public void startupPositions()
        {
            if (goalkeeper != null)
            {
                double distance = goalkeeper.Position.GetDistance(robots[0].startupPosition);
                if (distance > ROBOT_DIAMETER)
                    GoalKeeperDriver.DriveVelocity(goalkeeper.robotState, goalkeeper.startupPosition.x, goalkeeper.startupPosition.y, PotencialDriver.tinyVelocity);
                else
                    goalkeeper.Stop();
            }

            for (int i = 0; i < robots.Count; i++)
            {
                RobotController player = robots[i];
                double distance = player.Position.GetDistance(player.startupPosition);
                if (distance > ROBOT_DIAMETER)
                    PotencialDriver.DriveETA(player, player.startupPosition.x, player.startupPosition.y, distance / PotencialDriver.tinyVelocity);
                else
                    player.Stop();
            }
        }


        public void unassignFromStrategies()
        {
            for (int i = 0; i < Robots.Count; i++)
                Robots[i].isUsedInStrategy = false;

            if (GoalKeeper != null)
                GoalKeeper.isUsedInStrategy = false;
        }
    }
}
